from django.shortcuts import render,redirect,reverse
from django.contrib.auth.decorators import login_required
from django_redis import get_redis_connection
from django.http import JsonResponse
from django.db import transaction
from django.conf import settings
from goods.models import GoodsSKU
from user.models import Address
from order.models import OrderInfo, OrderGoods
from datetime import datetime
from alipay import AliPay, DCAliPay, ISVAliPay
import os

# Create your views here.
@login_required
def OrderIndex(request):
    '''订单提交页面'''
    if request.method=='GET':
        user = request.user
        try:
            pass
        except:
            pass

        conn = get_redis_connection('default')

    else:
        pass
    return render(request, 'df_order/place_order.html')



# 表单中的`checkbox`，只有被选中值才会被提交
@login_required
def OrderPlace(request):
    '''订单确定'''
    if request.method=='POST':
        user = request.user

        sku_ids = request.POST.getlist("sku_ids")
        print(sku_ids)
        if not sku_ids:
            redirect(reverse('cart:cart'))

        conn = get_redis_connection('default')
        cart_key = 'cart_%d' % user.id

        skus = []
        total_count = 0
        total_price = 0
        for sku_id in sku_ids:
            sku = GoodsSKU.objects.get(id=sku_id)
            count = conn.hget(cart_key,sku_id)
            amount = int(count)*sku.price
            sku.amount = amount
            sku.count = int(count)
            skus.append(sku)

            total_count += int(count)
            total_price += amount

        # 运费，子系统，需要单独开发
        trans_money = 10

        # 实付款
        pay_price = total_price + trans_money
        addr = Address.objects.filter(user = user.id)
        sku_ids = ','.join(sku_ids)
        print(addr)
        context = {
            'goods':skus,
            'trans_money':trans_money,
            'pay_price':pay_price,
            'addr':addr,
            'total_count':total_count,
            'total_amount':total_price,
            'sku_ids':sku_ids

        }
        return render(request, 'df_order/place_order.html', context)



#  用户提交订单时，需要传递的参数收获地址、支付方式、商品id
@transaction.atomic
def OrderCommit(request):
    '''订单提交'''
    if request.method == 'POST':
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res':0,'errmsg':'please login first'})

        addr_id = request.POST.get('addr_id')
        pay_method = request.POST.get('pay_method')
        sku_ids = request.POST.get('sku_ids')

        if not all([addr_id, pay_method, sku_ids]):
            return JsonResponse({'res':1,'errmsg':'information is Incomplete'})

        method = OrderInfo.objects.filter(pay_method=pay_method)
        print(pay_method)
        print(method)
        if method is None:
            return JsonResponse({'res':2,'errmsg':'pay method is not effective'})

        try:
            address = Address.objects.get(id = addr_id)
        except:
            return JsonResponse({'res':3,'errmsg':'Address is not effective'})

        # 创建订单核心业务
        order_id = datetime.now().strftime('%Y%m%d%H%M%S')+str(user.id)


        total_count = 0
        total_price = 0
        trans_price = 0

        # 设置事务保存点
        save_id = transaction.savepoint()
        try:
            order = OrderInfo.objects.create(order_id = order_id,
                                             user = user,
                                             addr = address,
                                             pay_method = pay_method,
                                             total_count = total_count,
                                             total_price = total_price,
                                             trans_price = trans_price,
                                             )

            # 向订单商品表添加商品
            conn = get_redis_connection('default')
            cart_key = 'cart_%d' % user.id

            sku_ids = sku_ids.split(',')

            for sku_id in sku_ids:
                for i in range(3):
                    try:
                        sku = GoodsSKU.objects.get(id=sku_id)
                        # 悲观锁,==>select * from df_goods_sku where id=sku_id for update;
                        # sku = GoodsSKU.objects.select_for_update.get(id=sku_id)
                        sku = GoodsSKU.objects.get(id=sku_id)
                    except:
                        transaction.savepoint_rollback(save_id)
                        return JsonResponse({'res': 4, 'errmsg': 'Goods is not exists'})

                    count = conn.hget(cart_key, sku_id)
                    if int(count) > sku.stock:
                        transaction.savepoint_rollback(save_id)
                        return JsonResponse({'res': 6, 'errmsg': 'goods stock is not enough'})

                    '''
                    # 修改商品销量、库存
                    sku.sales += int(count)
                    sku.stock -= int(count)
                    sku.save()
                    '''
                    orgin_stock = sku.stock
                    orgin_sales = sku.sales
                    new_stock = orgin_stock- int(count)
                    new_sales = orgin_sales + int(count)
                    # 乐观锁==>update df_goods_sku set stock=new_stock,sales=new_sales where id=sku_id and stock=orgin_stock
                    # 受影响的行数,缺点，当还有库存时，也会下单失败，循环3次
                    res = GoodsSKU.objects.filter(id=sku_id, stock=orgin_stock).update(stock=new_stock, sales = new_sales)
                    if res == 0:
                        if i == 2:
                            transaction.savepoint_rollback(save_id)
                            return JsonResponse({'res': 8, 'errmsg': 'order fail2'})
                        else:
                            continue
                    OrderGoods.objects.create(order=order,
                                              sku = sku,
                                              count = int(count),
                                              price = sku.price,
                                             )

                    total_count += int(count)
                    amount = sku.price*int(count)
                    total_price += amount
                    break

                order.total_count = total_count
                order.total_price = total_price
                order.save()

        except Exception as e:
            print(e)
            transaction.savepoint_rollback(save_id)
            return JsonResponse({'res': 7, 'errmsg': 'order fail'})

        # 提交事务,提交从保存点开始的sql
        transaction.savepoint_commit(save_id)
        # todo:清除购物车对应的记录
        conn.hdel(cart_key, *sku_ids)

        return JsonResponse({'res': 5, 'errmsg': 'success'})

# ajax post,order_id
# 支付宝接入
def OrderAliPay(request):
    if request.method == 'POST':
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res':0,'errmsg':'用户未登陆'})

        # 接收
        order_id = request.POST.get('order_id')
        # 检验
        if not order_id:
            return JsonResponse({'res':1,'errmsg':'该订单编号无效'})

        # 业务处理
        try:
            order = OrderInfo.objects.get(order_id=order_id,
                                         user = user,
                                         pay_method = 0,
                                         order_status = 0)
        except:
            return JsonResponse({'res':2,'errmsg':'该订单编号不存在'})

        #  初始化
        app_private_key = open(os.path.join(settings.BASE_DIR, 'apps/order/alipay_key/app_private_key.pem')).read()
        ali_public_key = open(os.path.join(settings.BASE_DIR, 'apps/order/alipay_key/alipay_public_key.pem')).read()
        alipay = AliPay(
            appid="2016102300744890",
            app_notify_url=None,  # 默认回调url
            app_private_key_string=app_private_key,
            # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            alipay_public_key_string=ali_public_key,
            sign_type="RSA2",  # RSA 或者 RSA2
            debug = True  # 默认False,True访问沙箱
        )

        # 调用接口
        # 电脑网站支付，需要跳转到https://openapi.alipay.com/gateway.do? + order_string
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order_id,
            total_amount=str(order.total_price),
            subject="天天生鲜%s"%(order_id),
            return_url=None,
            notify_url=None  # 可选, 不填则使用默认notify url
        )

        # 返回应答
        pay_url = 'https://openapi.alipaydev.com/gateway.do?' + order_string
        return JsonResponse({'res': 3, 'pay_url': pay_url})



def OrderAliCheck(request):
    if request.method == 'POST':
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res':0,'errmsg':'用户未登陆'})

        # 接收
        order_id = request.POST.get('order_id')
        # 检验
        if not order_id:
            return JsonResponse({'res':1,'errmsg':'该订单编号无效'})

        # 业务处理
        try:
            order = OrderInfo.objects.get(order_id=order_id,
                                         user = user,
                                         pay_method = 0,
                                         order_status = 0)
        except:
            return JsonResponse({'res':2,'errmsg':'该订单编号不存在'})

        #  初始化
        app_private_key = open(os.path.join(settings.BASE_DIR, 'apps/order/alipay_key/app_private_key.pem')).read()
        ali_public_key = open(os.path.join(settings.BASE_DIR, 'apps/order/alipay_key/alipay_public_key.pem')).read()
        alipay = AliPay(
            appid="2016102300744890",
            app_notify_url=None,  # 默认回调url
            app_private_key_string=app_private_key,
            # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            alipay_public_key_string=ali_public_key,
            sign_type="RSA2",  # RSA 或者 RSA2
            debug = True  # 默认False,True访问沙箱
        )

        # 调用接口
        while True:
            response = alipay.api_alipay_trade_query(
                out_trade_no=order_id
            )
            '''
            response = {
              "alipay_trade_query_response": {
                "trade_no": "2017032121001004070200176844",
                "code": "10000",
                "invoice_amount": "20.00",
                "open_id": "20880072506750308812798160715407",
                "fund_bill_list": [
                  {
                    "amount": "20.00",
                    "fund_channel": "ALIPAYACCOUNT"
                  }
                ],
                "buyer_logon_id": "csq***@sandbox.com",
                "send_pay_date": "2017-03-21 13:29:17",
                "receipt_amount": "20.00",
                "out_trade_no": "out_trade_no15",
                "buyer_pay_amount": "20.00",
                "buyer_user_id": "2088102169481075",
                "msg": "Success",
                "point_amount": "0.00",
                "trade_status": "TRADE_SUCCESS",
                "total_amount": "20.00"
              },
            '''
            code = response.get('code')  # 接口调用是否成功
            trade_status = response.get('trade_status') # 订单交易是否成功
            if code == '10000' and trade_status == 'TRADE_SUCCESS':
                # 交易成功，更新订单表数据
                order.trade_nu = response.get('trade_no')
                order.order_status = 3
                order.save()
                return JsonResponse({'res':3, 'errmsg':'支付成功'})

            elif code=='40004' or (code == '10000' and trade_status == 'WAIT_BUYER_PAY'):
                # 接口调用成功，处理业务中
                import time
                time.sleep(5)
                continue
            else:
                return JsonResponse({'res': 4, 'errmsg': '支付失败'})

